package game.units;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import game.enums.Alignment;
import game.enums.EquipSlots;
import game.enums.Size;
import game.mechanics.Equip;
import game.mechanics.Inventory;
import game.mechanics.Item;
import game.mechanics.Weapon;
import game.referenceValues.Feat;
import game.referenceValues.Power;
import game.referenceValues.Race;
import game.referenceValues.Skill;
import game.referenceValues.UnitClass;
import game.util.Die;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.xml.sax.InputSource;

public class Character extends Unit {

	private HashMap<String, Skill> skills;
	private ArrayList<game.referenceValues.UnitClass> classes;
	public ArrayList<Power> powers;
	public ArrayList<String> otherPowers;
	private ArrayList<Feat> feats;
	private int skillPointsLefts;
	public int bonusSkillPoints;
	public int bonusInitiative;
	private Inventory inventory;
	private Race race;
	public boolean hasNewClass;
	public int extraFeats;
	public int attributePointsLeft;
	public int moviments;
		
	private boolean bleeding;
	
	

	public Character() {
		super();
		extraFeats = 0;
		classes = new ArrayList<UnitClass>();
		skills = Skill.getDNDSkills();
		feats = new ArrayList<Feat>();
		powers = new ArrayList<Power>();
		otherPowers = new ArrayList<String>();
		skillPointsLefts = 0;
		bonusSkillPoints = 0;
		bonusInitiative = 0;
		hasNewClass = false;
		this.setLifePoints(0);
		attributePointsLeft = 32;
		this.inventory = new Inventory(100);
		moviments = 0;
	}

	public Race getRace() {
		return race;
	}

	public void setRace(Race race) {
		this.race = race;
	}

	/**
	 * Needs strength, therefore isn't on constructor
	 */
	public void initInventory() {
		int strength = getAttributes().get(Attribute.STRENGTH).getValue();
		inventory = new Inventory((int) (strength * 2.5));
	}

	public HashMap<String, Skill> getSkillsMap() {
		return skills;
	}

	public ArrayList<Feat> getFeats() {
		return feats;
	}

	public void setFeats(ArrayList<Feat> feats) {
		this.feats = feats;
	}

	public void addFeat(Feat feat) {
		this.feats.add(feat);
	}

	public boolean featTest(Feat toTest) {
		for (int i = 0; i < feats.size(); i++)
			if (toTest.getName() == feats.get(i).getName())
				return true;
		return false;
	}

	public void setSkillsMap(HashMap<String, Skill> skills) {
		this.skills = skills;
	}

	public void setSkill(String skillName, int base, int bonus) {
		Skill skill = skills.get(skillName);
		if (base > 0) {
			skill.setBase(base);
		}
		if (bonus > 0) {
			skill.setBonus(bonus);
		}
		skills.put(skillName, skill);
	}

	public boolean skillTest(String skillName, int challenge) {
		int result = Die.roll(20, 1);
		Skill skill = skills.get(skillName);
		int total = result + skill.currentValue();
		System.out.println(this.getName() + " rolled a " + result
				+ ", for a total of " + total);
		if (total >= challenge) {
			System.out.println(skillName + " test succeded");
			return true;
		}
		System.out.println(skillName + " test failed");
		return false;
	}

	public ArrayList<game.referenceValues.UnitClass> getClasses() {
		return classes;
	}

	public void setClasses(ArrayList<game.referenceValues.UnitClass> classes) {
		this.classes = classes;
	}

	public void addClass(game.referenceValues.UnitClass gameClass) {
		this.classes.add(gameClass);
	}

	public boolean hasClass(String name) {
		for (UnitClass cl : this.getClasses()) {
			if (cl.getName().equals(name))
				return true;
		}
		return false;
	}

	public static ArrayList<Character> getCharacters() {
		return getDNDCharacters();
	}

	public int getSkillPointsLefts() {
		return skillPointsLefts;
	}

	public void setSkillPointsLefts(int skillPointsLefts) {
		this.skillPointsLefts = skillPointsLefts;
	}
			

	public Inventory getInventory() {
		return inventory;
	}

	public void setInventory(Inventory inventory) {
		this.inventory = inventory;
	}

	public int getTotalLevel() {
		int lvl = 0;
		for (UnitClass clas : classes) {
			lvl = lvl + clas.getLvl();
		}
		return lvl;
	}

	public int remainingFeats() {
		int temp = 0;
		if (getLevel() == 1 || getLevel() % 3 == 0) {
			temp = temp + 1;
		}
		return temp;
	}

	public void setArmorClassValue() {
		int natural = 10 + this.getAttributes().get(Attribute.DEXTERITY)
				.getModifier();
		int armor = 0;
		for (EquipSlots slot : EquipSlots.values()) {
			if (inventory.getEquip(slot) != null) {
				armor = armor + inventory.getEquip(slot).getArmorClass();
			}
		}
		setArmorClass(armor + natural);

	}
	
	public int getInitiative() {
		return bonusInitiative;
	}

	public void levelUpCharacter() {
		int fort = (getAttributes().get(Attribute.STRENGTH)).getModifier() >= getAttributes()
				.get(Attribute.CONSTITUTION).getModifier() ? getAttributes()
				.get(Attribute.STRENGTH).getModifier() : getAttributes().get(
				Attribute.CONSTITUTION).getModifier();

		int re = (getAttributes().get(Attribute.DEXTERITY)).getModifier() >= getAttributes()
				.get(Attribute.INTELLIGENCE).getModifier() ? getAttributes()
				.get(Attribute.DEXTERITY).getModifier() : getAttributes().get(
				Attribute.INTELLIGENCE).getModifier();

		int wil = (getAttributes().get(Attribute.WISDOM)).getModifier() >= getAttributes()
				.get(Attribute.CHARISMA).getModifier() ? getAttributes().get(
				Attribute.WISDOM).getModifier() : getAttributes().get(
				Attribute.CHARISMA).getModifier();

		ArrayList<Integer> tempAtkBonus = new ArrayList<Integer>();
		HashMap<String, Feat> featMap = Feat.getDnDFeatsMap();
		int movBonus = 0;

		for (UnitClass unitClass : this.getClasses()) {
			fort = fort + unitClass.fortitude.get(unitClass.getLvl() - 1);
			wil = wil + unitClass.will.get(unitClass.getLvl() - 1);
			re = re + unitClass.reflex.get(unitClass.getLvl() - 1);
			String[] atkBonus = unitClass.atkBonus
					.get((unitClass.getLvl() - 1)).split("/");
			for (int i = 0; i < atkBonus.length; i++) {
				if (tempAtkBonus.size() > i) {
					tempAtkBonus
							.set(i,
									tempAtkBonus.get(i)
											+ Integer.parseInt(atkBonus[i]));
				} else {
					tempAtkBonus.add(Integer.parseInt(atkBonus[i]));
				}
			}

			ArrayList<String> feats = unitClass.featBonus.get((unitClass
					.getLvl()));
			for (String string : feats) {
				boolean contains = false;
				for (Feat feat : this.getFeats()) {
					if (feat.getName().equals(string)) {
						contains = true;
						break;
					}
				}
				if (!contains) {
					this.getFeats().add(featMap.get(string));
				}
			}
			for (int temp : unitClass.movBonus.get((unitClass.getLvl()))) {
				movBonus = movBonus + temp;
			}

			for (Power power : unitClass.powers.get((unitClass.getLvl()))) {
				boolean contains = false;
				for (Power charPower : this.powers) {
					if (power.getName().equals(charPower.getName())) {
						if (power.getQuantity() > charPower.getQuantity()) {
							charPower.setQuantity(power.getQuantity());
						}
						contains = true;
						break;
					}
				}
				if(power.getName().equals("extra feat"))
				{
					extraFeats++;
				}
				else if (!contains) {
					this.powers.add(power);
				}
			}
			for (String power : unitClass.others.get((unitClass.getLvl()))) {
				boolean contains = false;
				for (String charPower : this.otherPowers) {
					if (power.equals(charPower)) {
						contains = true;
						break;
					}
				}
				if (!contains) {
					this.otherPowers.add(power);
				}
			}
		}
		this.setFortitude(fort);
		this.setReflex(re);
		this.setWill(wil);
		this.attacksPerTurn = tempAtkBonus.size();
		int[] base = new int[tempAtkBonus.size()];
		for (int i = 0; i < tempAtkBonus.size(); i++) {
			base[i] = tempAtkBonus.get(i);
		}
		this.setInitiative(getAttributes().get(Attribute.DEXTERITY)
				.getModifier() + bonusInitiative);
		setAttackBase(base);
		this.getRace().setMovs(this.getRace().getMovs() + movBonus);

	}

	public void equip(Equip item, EquipSlots slot) {
		inventory.equip(item, feats, slot);
	}

	// //////////////////////////////////////////////////////
	// Interaction //
	// //////////////////////////////////////////////////////

	public boolean pickItem(Item item) {
		boolean wasPicked = inventory.pickUp(item);
		return wasPicked;
	}

	public void attack(Unit u) {

		Equip equip = inventory.getEquip(EquipSlots.MainHand);
		Weapon weapon;
		if (equip == null || !(equip instanceof Weapon)) {
			weapon = (Weapon)Item.getItemByID(11);
		}
		else {
			weapon = (Weapon) equip;
		}

		for (int i = 0; i < attacksPerTurn; i++) {

			float criticalModifier = 1f;

			// minimum on die for critical hit
			String criticalMinStr = weapon.getAttribute("minForCritical");
			int criticalMin = (criticalMinStr != null) ? Integer
					.parseInt(criticalMinStr) : 20;
			int roll = Die.roll(20, 1);
			if (roll == 1) {
				System.out.println("critical miss!");
			} else if (roll >= criticalMin) {
				System.out.println("critical hit!");
				String criticalModifierStr = weapon
						.getAttribute("criticalModifier");
				if (criticalModifierStr != null)
					criticalModifier = Float.parseFloat(criticalModifierStr);
			}

			// hit
			if (!u.wasHit(getAttackBase(i) + roll)) {
				System.out.println("miss!");
				return;
			}
			System.out.println("hit!");

			// damage
			u.takeDamage((int) (weapon.getDamage().getDamageValue() * criticalModifier));
		}

	}

	// ///////////////////////////////////////////////////////////////////////////////
	// /////////////////// XML methods /////////////////////
	// ///////////////////////////////////////////////////////////////////////////////

	public static String toXmlString(Character character) {
		// Lendo o XML

		try {
			Document doc = new Document();
			// Recuperamos o elemento root
			Element newCharacter = new Element("Character");

			Element Name = new Element("Name");
			Name.addContent(character.getName());
			newCharacter.addContent(Name);

			Element Race = new Element("Race");
			Race.addContent(character.getRace().getName());
			newCharacter.addContent(Race);

			Element Level = new Element("Level");
			Level.addContent("" + character.getLevel());
			newCharacter.addContent(Level);

			Element Classes = new Element("Classes");
			for (UnitClass unitClass : character.getClasses()) {
				Element Class = new Element("Class");
				Element className = new Element("Name");
				Element classLevel = new Element("Level");
				className.addContent(unitClass.getName());
				classLevel.addContent("" + unitClass.getLvl());
				Class.addContent(className);
				Class.addContent(classLevel);
				Classes.addContent(Class);
			}
			newCharacter.addContent(Classes);

			Element Gender = new Element("Gender");
			Gender.addContent(character.getGender());
			newCharacter.addContent(Gender);

			Element Size = new Element("Size");
			Size.addContent(character.getSize().name());
			newCharacter.addContent(Size);

			Element Deity = new Element("Deity");
			Deity.addContent(character.getDeity());
			newCharacter.addContent(Deity);

			Element Height = new Element("Height");
			Height.addContent(character.getHeight());
			newCharacter.addContent(Height);

			Element Weight = new Element("Weigth");
			Weight.addContent(character.getWeight());
			newCharacter.addContent(Weight);

			Element Age = new Element("Age");
			Age.addContent("" + character.getAge());
			newCharacter.addContent(Age);

			Element Alignment = new Element("Alignment");
			Alignment.addContent(character.getAlignment().name());
			newCharacter.addContent(Alignment);

			Element LifePoints = new Element("LifePoints");
			LifePoints.addContent("" + character.getLifePoints());
			newCharacter.addContent(LifePoints);

			Element Moviments = new Element("Moviments");
			Moviments.addContent("" + character.getRace().getMovs());
			newCharacter.addContent(Moviments);

			Element Initiative = new Element("Initiative");
			Initiative.addContent("" + character.getInitiative());
			newCharacter.addContent(Initiative);

			Element AC = new Element("AC");
			AC.addContent("" + character.getArmorClass());
			newCharacter.addContent(AC);

			Element Strength = new Element("Strength");
			Strength.addContent(""
					+ character.getAttributes().get(Attribute.STRENGTH)
							.getValue());
			newCharacter.addContent(Strength);

			Element Constitution = new Element("Constitution");
			Constitution.addContent(""
					+ character.getAttributes().get(Attribute.CONSTITUTION)
							.getValue());
			newCharacter.addContent(Constitution);

			Element Dexterity = new Element("Dexterity");
			Dexterity.addContent(""
					+ character.getAttributes().get(Attribute.DEXTERITY)
							.getValue());
			newCharacter.addContent(Dexterity);

			Element Intelligence = new Element("Intelligence");
			Intelligence.addContent(""
					+ character.getAttributes().get(Attribute.INTELLIGENCE)
							.getValue());
			newCharacter.addContent(Intelligence);

			Element Wisdom = new Element("Wisdom");
			Wisdom.addContent(""
					+ character.getAttributes().get(Attribute.WISDOM)
							.getValue());
			newCharacter.addContent(Wisdom);

			Element Charisma = new Element("Charisma");
			Charisma.addContent(""
					+ character.getAttributes().get(Attribute.CHARISMA)
							.getValue());
			newCharacter.addContent(Charisma);

			Element Fortitude = new Element("Fortitude");
			Fortitude.addContent("" + character.getFortitude());
			newCharacter.addContent(Fortitude);

			Element Reflexes = new Element("Reflexes");
			Reflexes.addContent("" + character.getReflex());
			newCharacter.addContent(Reflexes);

			Element Will = new Element("Will");
			Will.addContent("" + character.getWill());
			newCharacter.addContent(Will);

			Element AttackBase = new Element("AttackBase");
			String temp = "" + character.getAttackBase(0);
			for (int i = 1; i < character.getAttackBase().length; i++) {
				temp = temp + "/" + character.getAttackBase(i);
			}
			AttackBase.addContent(temp);
			newCharacter.addContent(AttackBase);

			Element SkillPointsLefts = new Element("SkillPointsLefts");
			SkillPointsLefts.addContent(""
					+ character.getSkillPointsLefts());
			newCharacter.addContent(SkillPointsLefts);

			Element BonusSkillPoints = new Element("BonusSkillPoints");
			BonusSkillPoints.addContent("" + character.bonusSkillPoints);
			newCharacter.addContent(BonusSkillPoints);

			Element ExtraFeats = new Element("ExtraFeats");
			ExtraFeats.addContent("" + character.extraFeats);
			newCharacter.addContent(ExtraFeats);

			String[] skillNames = { "Appraise", "Balance", "Bluff",
					"Climb", "Concentration", "Craft", "Diplomacy",
					"Disable Device", "Disguise", "Escape Artist",
					"Gather Information", "Handle Animal", "Heal", "Hide",
					"Intimidate", "Jump", "Knowledge", "Listen",
					"Move Silently", "Open Lock", "Perform", "Ride",
					"Search", "Sense Motive", "Sleight of Hand",
					"Spellcraft", "Spot", "Survival", "Swim", "Tumble",
					"Use Magic Device" };

			Element Skills = new Element("Skills");
			for (String sk : skillNames) {
				Skill skill = character.getSkillsMap().get(sk);
				Element Skill = new Element("Skill");
				Element SkillName = new Element("Name");
				Element SkillValue = new Element("Base");
				SkillName.addContent(skill.getName());
				SkillValue.addContent("" + skill.getBase());
				Skill.addContent(SkillName);
				Skill.addContent(SkillValue);
				Skills.addContent(Skill);
			}
			newCharacter.addContent(Skills);

			Element Powers = new Element("Powers");
			for (Power power : character.powers) {
				Element Power = new Element("Power");
				Element Name1 = new Element("Name");
				Element Quantity = new Element("Quantity");
				Name1.addContent(power.getName());
				Quantity.addContent("" + power.getQuantity());
				Power.addContent(Name1);
				Power.addContent(Quantity);
				Powers.addContent(Power);
			}
			newCharacter.addContent(Powers);

			Element Others = new Element("Others");
			for (String power : character.otherPowers) {
				Element Power = new Element("Other");
				Element Name1 = new Element("Name");
				Name1.addContent(power);
				Power.addContent(Name1);
				Others.addContent(Power);
			}
			newCharacter.addContent(Others);

			Element Feats = new Element("Feats");
			for (Feat feat : character.getFeats()) {
				Element Feat = new Element("Feat");
				Element Name1 = new Element("Name");
				Name1.addContent(feat.getName());
				Feat.addContent(Name1);
				Feats.addContent(Feat);
			}
			newCharacter.addContent(Feats);

			Element Inventory = new Element("Inventory");
			for (Item item : character.inventory.getItens()) {
				Element Item = new Element("Item");
				Element ID = new Element("ID");
				ID.addContent("" + item.getItemIdentifier());
				Item.addContent(ID);
				Inventory.addContent(Item);
			}
			newCharacter.addContent(Inventory);

			Element Equips = new Element("Equipments");
			for (EquipSlots slot : EquipSlots.values()) {
				Equip equip = character.inventory.getEquip(slot);
				if (equip.getItemIdentifier() != 0) {
					Element Equip = new Element("Equip");
					Element ID = new Element("ID");
					ID.addContent("" + equip.getItemIdentifier());
					Equip.addContent(ID);
					Equips.addContent(Equip);
				}
			}
			newCharacter.addContent(Equips);

			doc.addContent(newCharacter);

			// serialize it onto System.out

			// Imprimindo o XML
			XMLOutputter xout = new XMLOutputter();
			return xout.outputString(doc);
			
		} catch (Exception e) {
			System.out.println(e.getMessage());
			return "";
		}		
	}
	
	public static Character fromXmlString(String xmlString) {
		
		Character character = new Character();
		
		try {
			Document doc = new SAXBuilder().build(new InputSource(new ByteArrayInputStream(xmlString.getBytes())));
			// Recuperamos o elemento root
			Element element = doc.getRootElement();

			Race raceGetter = new Race();
			ArrayList<Race> races = raceGetter.getRaces();
			UnitClass uc = new UnitClass();
			ArrayList<UnitClass> classes = uc.getBasicClasses();

			Element el = element.getChild("Equipments");
			List modElements = el.getChildren();
			Iterator j = modElements.iterator();
			while (j.hasNext()) {
				Equip equip = new Equip();
				Element temp = (Element) j.next();
				equip.setItemIdentifier(Integer.parseInt(temp
						.getChildText("ID")));
				equip.getEquipByID();
				// character.inventory.equip(equip);
			}

			Element el2 = element.getChild("Inventory");
			List itemElements = el2.getChildren();
			Iterator k = itemElements.iterator();
			while (k.hasNext()) {
				Element temp = (Element) k.next();
				int itemId = Integer.parseInt(temp.getChildText("ID"));
				Item item = Item.getItemByID(itemId);
				character.inventory.pickUpItem(item);
			}

			Element el3 = element.getChild("Skills");
			List skillElements = el3.getChildren();
			Iterator i3 = skillElements.iterator();
			while (i3.hasNext()) {
				Element temp = (Element) i3.next();
				Skill skill = new Skill(temp.getChildText("Name"),
						temp.getChildText("Description"),
						temp.getChildText("Base"));
				character.skills.put(skill.getName(), skill);
			}

			Element el4 = element.getChild("Others");
			List otherPowers = el4.getChildren();
			Iterator i4 = otherPowers.iterator();
			while (i4.hasNext()) {
				Element temp = (Element) i4.next();
				String other = temp.getChildText("Name");
				character.otherPowers.add(other);
			}

			Element el5 = element.getChild("Powers");
			List powers = el5.getChildren();
			Iterator i5 = powers.iterator();
			while (i5.hasNext()) {
				Element temp = (Element) i5.next();
				Power power = new Power(temp.getChildText("Name"), "",
						1, Integer.parseInt(temp
								.getChildText("Quantity")));
				character.powers.add(power);
			}

			Element el6 = element.getChild("Feats");
			List feats = el6.getChildren();
			Iterator i6 = feats.iterator();
			while (i6.hasNext()) {
				Element temp = (Element) i6.next();
				Feat feat = new Feat(temp.getChildText("Name"));
				character.feats.add(feat);
			}

			Element el7 = element.getChild("Classes");
			List XMLclasses = el7.getChildren();
			Iterator i7 = XMLclasses.iterator();
			while (i7.hasNext()) {
				Element temp = (Element) i7.next();
				for (UnitClass cl : classes) {
					if (cl.getName().equals(
							temp.getChildText("Name"))) {
						UnitClass ucl = cl.cloneClass();
						int lvl = Integer.parseInt(temp
								.getChildText("Level"));
						ucl.setLvl(lvl);
						character.addClass(ucl);
					}
				}
			}

			character.setName(element.getChildText("Name"));
			character.setAlignment(Alignment.valueOf(element
					.getChildText("Alignment")));
			character
					.setSize(Size.valueOf(element.getChildText("Size")));

			Race charRace = new Race();
			for (Race race : races) {
				if (race.getName().equals(element.getChildText("Race"))) {
					charRace = race;
					character.moviments = (Integer.parseInt(element
							.getChildText("Moviments")));
				}
			}
			character.setRace((charRace));
			character.setLifePoints(Integer.parseInt((element
					.getChildText("LifePoints"))));
			character.setInitiative(Integer.parseInt((element
					.getChildText("Initiative"))));
			character.setArmorClass(Integer.parseInt((element
					.getChildText("AC"))));
			character.setFortitude(Integer.parseInt((element
					.getChildText("Fortitude"))));
			character.setReflex(Integer.parseInt((element
					.getChildText("Reflexes"))));
			character.setWill(Integer.parseInt((element
					.getChildText("Will"))));
			character.setLevel(Integer.parseInt((element
					.getChildText("Level"))));
			String[] temp = ((element.getChildText("AttackBase")))
					.split("/");
			int[] atk = new int[temp.length];
			for (int index = 0; index < temp.length; index++) {
				atk[index] = Integer.parseInt(temp[index]);
			}
			character.setAttackBase(atk);
			character.setGender(element.getChildText("Gender"));
			character.setDeity(element.getChildText("Deity"));
			character.setHeight(element.getChildText("Height"));
			character.setWeight(element.getChildText("Weigth"));
			character.setAge(Integer.parseInt((element
					.getChildText("Age"))));
			character.skillPointsLefts = (Integer.parseInt((element
					.getChildText("SkillPointsLefts"))));
			character.bonusSkillPoints = (Integer.parseInt((element
					.getChildText("BonusSkillPoints"))));
			character.extraFeats = (Integer.parseInt((element
					.getChildText("ExtraFeats"))));
			Attribute att = new Attribute();
			character.setAttributes(att.generateAttributes
					(Integer.parseInt((element.getChildText("Strength"))), 
					Integer.parseInt((element.getChildText("Constitution"))), 
					Integer.parseInt((element.getChildText("Dexterity"))), 
					Integer.parseInt((element.getChildText("Intelligence"))),
					Integer.parseInt((element.getChildText("Wisdom"))),
					Integer.parseInt((element.getChildText("Charisma")))));
			character.attacksPerTurn = atk.length;
			character.attributePointsLeft = 0;
			
		} catch (JDOMException e) {
			e.getMessage();
			e.printStackTrace();
		} catch (IOException e) {
			e.getMessage();
			e.printStackTrace();
		}
		return character;
	}
	
	public static void addDNDCharacter(Character character) {
		// Lendo o XML

		try {
			FileInputStream XMLin = new FileInputStream("characters.xml");
			SAXBuilder sb = new SAXBuilder();

			try {
				Document doc = sb.build(XMLin);
				// Recuperamos o elemento root
				Element xmlCharacter = doc.getRootElement();

				Element newCharacter = new Element("Character");

				Element Name = new Element("Name");
				Name.addContent(character.getName());
				newCharacter.addContent(Name);

				Element Race = new Element("Race");
				Race.addContent(character.getRace().getName());
				newCharacter.addContent(Race);

				Element Level = new Element("Level");
				Level.addContent("" + character.getLevel());
				newCharacter.addContent(Level);

				Element Classes = new Element("Classes");
				for (UnitClass unitClass : character.getClasses()) {
					Element Class = new Element("Class");
					Element className = new Element("Name");
					Element classLevel = new Element("Level");
					className.addContent(unitClass.getName());
					classLevel.addContent("" + unitClass.getLvl());
					Class.addContent(className);
					Class.addContent(classLevel);
					Classes.addContent(Class);
				}
				newCharacter.addContent(Classes);

				Element Gender = new Element("Gender");
				Gender.addContent(character.getGender());
				newCharacter.addContent(Gender);

				Element Size = new Element("Size");
				Size.addContent(character.getSize().name());
				newCharacter.addContent(Size);

				Element Deity = new Element("Deity");
				Deity.addContent(character.getDeity());
				newCharacter.addContent(Deity);

				Element Height = new Element("Height");
				Height.addContent(character.getHeight());
				newCharacter.addContent(Height);

				Element Weight = new Element("Weigth");
				Weight.addContent(character.getWeight());
				newCharacter.addContent(Weight);

				Element Age = new Element("Age");
				Age.addContent("" + character.getAge());
				newCharacter.addContent(Age);

				Element Alignment = new Element("Alignment");
				Alignment.addContent(character.getAlignment().name());
				newCharacter.addContent(Alignment);

				Element LifePoints = new Element("LifePoints");
				LifePoints.addContent("" + character.getLifePoints());
				newCharacter.addContent(LifePoints);

				Element Moviments = new Element("Moviments");
				Moviments.addContent("" + character.getRace().getMovs());
				newCharacter.addContent(Moviments);

				Element Initiative = new Element("Initiative");
				Initiative.addContent("" + character.getInitiative());
				newCharacter.addContent(Initiative);

				Element AC = new Element("AC");
				AC.addContent("" + character.getArmorClass());
				newCharacter.addContent(AC);

				Element Strength = new Element("Strength");
				Strength.addContent(""
						+ character.getAttributes().get(Attribute.STRENGTH)
								.getValue());
				newCharacter.addContent(Strength);

				Element Constitution = new Element("Constitution");
				Constitution.addContent(""
						+ character.getAttributes().get(Attribute.CONSTITUTION)
								.getValue());
				newCharacter.addContent(Constitution);

				Element Dexterity = new Element("Dexterity");
				Dexterity.addContent(""
						+ character.getAttributes().get(Attribute.DEXTERITY)
								.getValue());
				newCharacter.addContent(Dexterity);

				Element Intelligence = new Element("Intelligence");
				Intelligence.addContent(""
						+ character.getAttributes().get(Attribute.INTELLIGENCE)
								.getValue());
				newCharacter.addContent(Intelligence);

				Element Wisdom = new Element("Wisdom");
				Wisdom.addContent(""
						+ character.getAttributes().get(Attribute.WISDOM)
								.getValue());
				newCharacter.addContent(Wisdom);

				Element Charisma = new Element("Charisma");
				Charisma.addContent(""
						+ character.getAttributes().get(Attribute.CHARISMA)
								.getValue());
				newCharacter.addContent(Charisma);

				Element Fortitude = new Element("Fortitude");
				Fortitude.addContent("" + character.getFortitude());
				newCharacter.addContent(Fortitude);

				Element Reflexes = new Element("Reflexes");
				Reflexes.addContent("" + character.getReflex());
				newCharacter.addContent(Reflexes);

				Element Will = new Element("Will");
				Will.addContent("" + character.getWill());
				newCharacter.addContent(Will);

				Element AttackBase = new Element("AttackBase");
				String temp = "" + character.getAttackBase(0);
				for (int i = 1; i < character.getAttackBase().length; i++) {
					temp = temp + "/" + character.getAttackBase(i);
				}
				AttackBase.addContent(temp);
				newCharacter.addContent(AttackBase);

				Element SkillPointsLefts = new Element("SkillPointsLefts");
				SkillPointsLefts.addContent(""
						+ character.getSkillPointsLefts());
				newCharacter.addContent(SkillPointsLefts);

				Element BonusSkillPoints = new Element("BonusSkillPoints");
				BonusSkillPoints.addContent("" + character.bonusSkillPoints);
				newCharacter.addContent(BonusSkillPoints);

				Element ExtraFeats = new Element("ExtraFeats");
				ExtraFeats.addContent("" + character.extraFeats);
				newCharacter.addContent(ExtraFeats);

				String[] skillNames = { "Appraise", "Balance", "Bluff",
						"Climb", "Concentration", "Craft", "Diplomacy",
						"Disable Device", "Disguise", "Escape Artist",
						"Gather Information", "Handle Animal", "Heal", "Hide",
						"Intimidate", "Jump", "Knowledge", "Listen",
						"Move Silently", "Open Lock", "Perform", "Ride",
						"Search", "Sense Motive", "Sleight of Hand",
						"Spellcraft", "Spot", "Survival", "Swim", "Tumble",
						"Use Magic Device" };

				Element Skills = new Element("Skills");
				for (String sk : skillNames) {
					Skill skill = character.getSkillsMap().get(sk);
					Element Skill = new Element("Skill");
					Element SkillName = new Element("Name");
					Element SkillValue = new Element("Base");
					SkillName.addContent(skill.getName());
					SkillValue.addContent("" + skill.getBase());
					Skill.addContent(SkillName);
					Skill.addContent(SkillValue);
					Skills.addContent(Skill);
				}
				newCharacter.addContent(Skills);

				Element Powers = new Element("Powers");
				for (Power power : character.powers) {
					Element Power = new Element("Power");
					Element Name1 = new Element("Name");
					Element Quantity = new Element("Quantity");
					Name1.addContent(power.getName());
					Quantity.addContent("" + power.getQuantity());
					Power.addContent(Name1);
					Power.addContent(Quantity);
					Powers.addContent(Power);
				}
				newCharacter.addContent(Powers);

				Element Others = new Element("Others");
				for (String power : character.otherPowers) {
					Element Power = new Element("Other");
					Element Name1 = new Element("Name");
					Name1.addContent(power);
					Power.addContent(Name1);
					Others.addContent(Power);
				}
				newCharacter.addContent(Others);

				Element Feats = new Element("Feats");
				for (Feat feat : character.getFeats()) {
					Element Feat = new Element("Feat");
					Element Name1 = new Element("Name");
					Name1.addContent(feat.getName());
					Feat.addContent(Name1);
					Feats.addContent(Feat);
				}
				newCharacter.addContent(Feats);

				Element Inventory = new Element("Inventory");
				for (Item item : character.inventory.getItens()) {
					Element Item = new Element("Item");
					Element ID = new Element("ID");
					ID.addContent("" + item.getItemIdentifier());
					Item.addContent(ID);
					Inventory.addContent(Item);
				}
				newCharacter.addContent(Inventory);

				Element Equips = new Element("Equipments");
				for (EquipSlots slot : EquipSlots.values()) {
					Equip equip = character.inventory.getEquip(slot);
					if (equip.getItemIdentifier() != 0) {
						Element Equip = new Element("Equip");
						Element ID = new Element("ID");
						ID.addContent("" + equip.getItemIdentifier());
						Equip.addContent(ID);
						Equips.addContent(Equip);
					}
				}
				newCharacter.addContent(Equips);

				xmlCharacter.addContent(newCharacter);

				// serialize it onto System.out

				// Imprimindo o XML
				XMLin.close();
				XMLOutputter xout = new XMLOutputter();
				try {
					FileOutputStream XML = new FileOutputStream(
							"characters.xml");
					try {
						xout.output(doc, XML);
						XML.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			} catch (JDOMException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static ArrayList<Character> getDNDCharacters() {
		// Lendo o XML
		ArrayList<Character> xmlCharacters = new ArrayList<Character>();
		try {
			FileInputStream XMLin = new FileInputStream("characters.xml");
			SAXBuilder sb = new SAXBuilder();
			try {
				Document doc = sb.build(XMLin);
				// Recuperamos o elemento root
				Element xmlskills = doc.getRootElement();
				// Recuperamos os elementos filhos (children)
				List elements = xmlskills.getChildren();
				Iterator i = elements.iterator();

				Race raceGetter = new Race();
				ArrayList<Race> races = raceGetter.getRaces();
				UnitClass uc = new UnitClass();
				ArrayList<UnitClass> classes = uc.getBasicClasses();

				while (i.hasNext()) {
					Character character = new Character();
					Element element = (Element) i.next();

					Element el = element.getChild("Equipments");
					List modElements = el.getChildren();
					Iterator j = modElements.iterator();
					while (j.hasNext()) {
						Equip equip = new Equip();
						Element temp = (Element) j.next();
						equip.setItemIdentifier(Integer.parseInt(temp
								.getChildText("ID")));
						equip.getEquipByID();
						// character.inventory.equip(equip);
					}

					Element el2 = element.getChild("Inventory");
					List itemElements = el2.getChildren();
					Iterator k = itemElements.iterator();
					while (k.hasNext()) {
						Element temp = (Element) k.next();
						int itemId = Integer.parseInt(temp.getChildText("ID"));
						Item item = Item.getItemByID(itemId);
						character.inventory.pickUpItem(item);
					}

					Element el3 = element.getChild("Skills");
					List skillElements = el3.getChildren();
					Iterator i3 = skillElements.iterator();
					while (i3.hasNext()) {
						Element temp = (Element) i3.next();
						Skill skill = new Skill(temp.getChildText("Name"),
								temp.getChildText("Description"),
								temp.getChildText("Base"));
						character.skills.put(skill.getName(), skill);
					}

					Element el4 = element.getChild("Others");
					List otherPowers = el4.getChildren();
					Iterator i4 = otherPowers.iterator();
					while (i4.hasNext()) {
						Element temp = (Element) i4.next();
						String other = temp.getChildText("Name");
						character.otherPowers.add(other);
					}

					Element el5 = element.getChild("Powers");
					List powers = el5.getChildren();
					Iterator i5 = powers.iterator();
					while (i5.hasNext()) {
						Element temp = (Element) i5.next();
						Power power = new Power(temp.getChildText("Name"), "",
								1, Integer.parseInt(temp
										.getChildText("Quantity")));
						character.powers.add(power);
					}

					Element el6 = element.getChild("Feats");
					List feats = el6.getChildren();
					Iterator i6 = feats.iterator();
					while (i6.hasNext()) {
						Element temp = (Element) i6.next();
						Feat feat = new Feat(temp.getChildText("Name"));
						character.feats.add(feat);
					}

					Element el7 = element.getChild("Classes");
					List XMLclasses = el7.getChildren();
					Iterator i7 = XMLclasses.iterator();
					while (i7.hasNext()) {
						Element temp = (Element) i7.next();
						for (UnitClass cl : classes) {
							if (cl.getName().equals(
									temp.getChildText("Name"))) {
								UnitClass ucl = cl.cloneClass();
								int lvl = Integer.parseInt(temp
										.getChildText("Level"));
								ucl.setLvl(lvl);
								character.addClass(ucl);
							}
						}
					}

					character.setName(element.getChildText("Name"));
					character.setAlignment(Alignment.valueOf(element
							.getChildText("Alignment")));
					character
							.setSize(Size.valueOf(element.getChildText("Size")));

					Race charRace = new Race();
					for (Race race : races) {
						if (race.getName().equals(element.getChildText("Race"))) {
							charRace = race;
							character.moviments = (Integer.parseInt(element
									.getChildText("Moviments")));
						}
					}
					character.setRace((charRace));
					character.setLifePoints(Integer.parseInt((element
							.getChildText("LifePoints"))));
					character.setInitiative(Integer.parseInt((element
							.getChildText("Initiative"))));
					character.setArmorClass(Integer.parseInt((element
							.getChildText("AC"))));
					character.setFortitude(Integer.parseInt((element
							.getChildText("Fortitude"))));
					character.setReflex(Integer.parseInt((element
							.getChildText("Reflexes"))));
					character.setWill(Integer.parseInt((element
							.getChildText("Will"))));
					character.setLevel(Integer.parseInt((element
							.getChildText("Level"))));
					String[] temp = ((element.getChildText("AttackBase")))
							.split("/");
					int[] atk = new int[temp.length];
					for (int index = 0; index < temp.length; index++) {
						atk[index] = Integer.parseInt(temp[index]);
					}
					character.setAttackBase(atk);
					character.setGender(element.getChildText("Gender"));
					character.setDeity(element.getChildText("Deity"));
					character.setHeight(element.getChildText("Height"));
					character.setWeight(element.getChildText("Weigth"));
					character.setAge(Integer.parseInt((element
							.getChildText("Age"))));
					character.skillPointsLefts = (Integer.parseInt((element
							.getChildText("SkillPointsLefts"))));
					character.bonusSkillPoints = (Integer.parseInt((element
							.getChildText("BonusSkillPoints"))));
					character.extraFeats = (Integer.parseInt((element
							.getChildText("ExtraFeats"))));
					Attribute att = new Attribute();
					character.setAttributes(att.generateAttributes
							(Integer.parseInt((element.getChildText("Strength"))), 
							Integer.parseInt((element.getChildText("Constitution"))), 
							Integer.parseInt((element.getChildText("Dexterity"))), 
							Integer.parseInt((element.getChildText("Intelligence"))),
							Integer.parseInt((element.getChildText("Wisdom"))),
							Integer.parseInt((element.getChildText("Charisma")))));
					character.attacksPerTurn = atk.length;
					character.attributePointsLeft = 0;
					xmlCharacters.add(character);
					XMLin.close();
				}
			} catch (JDOMException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return xmlCharacters;
	}
	
	public static void removeDNDCharacter(Character character) {
		// Lendo o XML
		
		try {
			FileInputStream XMLin = new FileInputStream("characters.xml");
			SAXBuilder sb = new SAXBuilder();

			try {
				Document doc = sb.build(XMLin);
				// Recuperamos o elemento root
				Element xmlCharacters = doc.getRootElement();
				List elements = xmlCharacters.getChildren();
				Iterator i = elements.iterator();
				int toRemove = 0;
				while (i.hasNext()) {
					Element element = (Element) i.next();
					String name = element.getChildText("Name");
					if (name.equals(character.getName())) {
						xmlCharacters.removeContent(toRemove);
						break;
					}
					toRemove++;
				}
				try {
					XMLin.close();
				} catch (Exception e) {
					// TODO: handle exception
				}
				// serialize it onto System.out

				// Imprimindo o XML
				XMLOutputter xout = new XMLOutputter();
				try {
					FileOutputStream XML = new FileOutputStream("characters.xml");
					try {
						xout.output(doc, XML);
						XML.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			} catch (JDOMException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public boolean isBleeding() {
		return bleeding;
	}

	public void setBleeding(boolean b) {
		bleeding = b;
	}

	public void alterCurrenHP(int damage) {
		setCurrentHP(this.getCurrentHP() + damage);
	}

	
}
